package model

import (
	"cgs-server/helper"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
	"time"
)

// 基础 struct
type BaseModel struct {
	BaseId     primitive.ObjectID `json:"-" bson:"_id,omitempty"`
	CreateUser string             `json:"createUser" bson:"createUser"`                     // 创建人
	CreateDept string             `json:"createDept" bson:"createDept"`                     // 创建部门
	CreateTime time.Time          `json:"createTime,omitempty" bson:"createTime,omitempty"` // 创建时间
	UpdateTime time.Time          `json:"updateTime,omitempty" bson:"updateTime,omitempty"` // 修改时间
	UpdateUser string             `json:"updateUser" bson:"updateUser"`                     // 更新人
	IsDeleted  *int               `json:"-" bson:"isDeleted"`                               // 是否删除
	Status     *int               `json:"status" bson:"status"`                             // 业务状态
	Owner      string             `json:"owner" bson:"owner"`

	UserId string `json:"-" bson:"UserID,omitempty"` // 用来传递当前用户id，不保存和返回这个字段
}

type TenantModel struct {
	BaseModel `json:",inline" bson:",inline"`
	TenantId  string `json:"tenantId,omitempty" bson:"tenantId"`
}

func (t *TenantModel) GetTenantId() string {
	return t.TenantId
}
func (t *TenantModel) SetTenantId(tenantId string) {
	t.TenantId = tenantId
}

// service add 结果
type AddResult struct {
	Id    string
	Msg   string
	Error error
}

// 传输 data 和 user
type DataUserModel struct {
	Data           interface{}
	User           *User
	Page           *Page
	Filter         *bson.M              // 过滤条件
	Options        *options.FindOptions // 查询配置
	FindOneOptions *options.FindOneOptions
	Simplify       bool // 返回简化结构数据
}

// 配置分页参数
func (d *DataUserModel) ResolvePageOption() {
	if d.Options == nil {
		d.Options = &options.FindOptions{}
	}
	if d.Page != nil {
		skip := int64(0)
		if d.Page.Current > 0 {
			skip = (d.Page.Current - 1) * d.Page.Size
		} else {
			d.Page.Current += 1
		}
		if d.Page.Size == 0 {
			d.Page.Size = 100
		}
		d.Options.Skip = &skip
		d.Options.Limit = &d.Page.Size
	}
}

// 分页参数
type Page struct {
	Current int64
	Size    int64
}

type PageResult struct {
	Records interface{} `json:"records"`
	Total   int64       `json:"total"`
	Size    int64       `json:"size"`
}

type IModel interface {
	GetId() string
	SetId(id primitive.ObjectID)
	GetUserId() string
}

// 设置基础属性
func (m *BaseModel) ResolveEntity(model IModel, user *User) {
	id := model.GetId()
	now := time.Now()
	// id 是 "000000000000000000000000" 时，对应 ObjectID 的零值
	if id == "" || id == primitive.NilObjectID.Hex() {
		newId := primitive.NewObjectID()
		model.SetId(newId)
		/*if user != nil {
			m.CreateUser = user.GetId()
			m.CreateDept = user.DeptID
			m.UpdateUser = user.GetId()
		}

		if m.Status == nil {
			status := 1
			m.Status = &status
		}

		m.CreateTime = now*/
	} /*else {
		if user != nil {
			m.UpdateUser = user.GetId()
		}
	}*/

	if user != nil {
		m.CreateUser = user.GetId()
		m.CreateDept = user.DeptID
		m.UpdateUser = user.GetId()
		m.Owner = user.GetId()
	}
	if m.Status == nil {
		status := 1
		m.Status = &status
	}
	m.CreateTime = now

	m.UpdateTime = now
	isDeleted := 0
	m.IsDeleted = &isDeleted

	// 获取 TenantId
	tenantId := helper.GetFieldValue(model, "TenantId")
	// 如果有 TenantId，且没有值, 使用用户的 TenantId 设置 TenantId
	if tenantId.IsValid() {
		if tenantId.IsZero() && user != nil {
			tenantId.SetString(user.TenantId)
		}
	}
}

func (m *BaseModel) TimeUtcToCst() {
	m.UpdateTime = m.UpdateTime.Add(time.Hour * time.Duration(8))
	m.CreateTime = m.CreateTime.Add(time.Hour * time.Duration(8))
}

// 生成基本信息的更新条件
func (m *BaseModel) ResolveUpdateCondition(model IModel, user *User, update *bson.M) {
	id := model.GetId()
	now := time.Now()
	if id == "" {
		return
	}
	updateMap := *update
	if user != nil {
		updateMap["updateUser"] = user.GetId()
	}
	updateMap["updateTime"] = now
}

// 设置基本过滤条件
func (m *BaseModel) ResolveFilter(model IModel, user *User, filter *bson.M) {
	filterMap := *filter
	//filterMap["isDeleted"] = 0
	deleteArr := bson.A{
		bson.M{
			"isDeleted": 0,
		},
		bson.M{
			"isDeleted": bson.M{
				"$exists": false,
			},
		},
	}
	filterArr := bson.A{
		bson.M{"$or": deleteArr},
	}
	if filterMap["tenantId"] == nil || filterMap["tenantId"] == "" {
		// 获取 TenantId
		tId := ""
		tenantId := helper.GetFieldValue(model, "TenantId")
		if tenantId.IsValid() {
			if tenantId.IsZero() && user != nil && user.TenantId != "" {
				//filterMap["tenantId"] = user.TenantId
				tId = user.TenantId
			} else {
				//filterMap["tenantId"] = tenantId.String()
				tId = tenantId.String()
			}
			if tId != "" {
				tenantArr := bson.A{
					bson.M{
						"tenantId": tId,
					},
				}
				tenantArr = append(tenantArr, bson.M{
					"tenantId": bson.M{
						"$exists": false,
					},
				})
				if tId == "000000" {
					tenantArr = append(tenantArr, bson.M{
						"tenantId": "",
					})
				}
				filterArr = append(filterArr, bson.M{
					"$or": tenantArr,
				})
			}

		}
	}
	if filterMap["$and"] != nil {
		if and, ok := filterMap["$and"].(primitive.A); ok {
			and = append(and, filterArr...)
			filterMap["$and"] = and
		}
	} else {
		filterMap["$and"] = filterArr
	}
}

func (m *BaseModel) ResolveOptions(page *Page) *options.FindOptions {
	opts := &options.FindOptions{
		Sort: bson.M{
			"updateTime": -1,
		},
		Projection: bson.M{
			"_id":       0,
			"isDeleted": 0,
		},
	}
	if page != nil {
		skip := int64(0)
		if page.Current > 0 {
			skip = (page.Current - 1) * page.Size
		}
		if page.Size != 0 {
			opts.Skip = &skip
			opts.Limit = &page.Size
		}
	}
	return opts
}

// 修改状态
func (m *BaseModel) ChangeStatus(model IModel, user *User, update *bson.M) {

}

// 逻辑删除
func (m *BaseModel) DeleteLogic(model IModel, user *User, update *bson.M) {
	m.ResolveUpdateCondition(model, user, update)
	updateMap := *update
	updateMap["isDeleted"] = 1
}

func (m *BaseModel) GetUserId() string {
	return m.UserId
}

func (m *BaseModel) GetId() string {
	return m.BaseId.Hex()
}

func (m *BaseModel) SetId(id primitive.ObjectID) {
	m.BaseId = id
}

type BaseModels []BaseModel

func (b *BaseModels) TimeUtcToCst() {
	for _, bm := range *b {
		bm.TimeUtcToCst()
	}
}
